/*
MoniBabyTor - a webcam based monitoring app for babies
    Copyright (C) 2013 Assaf Paz

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "cameralogic.h"
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>

CameraLogic::CameraLogic(SettingsDataModel& dataModel, MJpegFile &mjpegFile, WavFile& waveFile, QObject *parent) :
    QObject(parent),
    _dataModel(dataModel),
    _audioFeed(NULL),
    _videoFeed(NULL),
    _wavFile(waveFile),
    _mjpegFile(mjpegFile)
{
    connect(&_nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(streamEnded(QNetworkReply*)));
    connect(&_mjpegFile, SIGNAL(imageReceived(QImage*)), this, SIGNAL(imageReceived(QImage*)));

    connect(&_wavFile, SIGNAL(error(QString)), &_dataModel, SIGNAL(error(QString)));
    connect(&_wavFile, SIGNAL(peakDetected()), this, SLOT(onPeakDetected()));
    connect(&_wavFile, SIGNAL(rmsLevelChanged(int)), &_dataModel, SIGNAL(rmsLevelChanged(int)));
    connect(&_dataModel, SIGNAL(sensitivityChanged(int)), &_wavFile, SLOT(onPeakThresholdChanged(int)));
    connect(&_dataModel, SIGNAL(outputVolumeChanged(int)), &_wavFile, SLOT(onVolumeChanged(int)));
    connect(&_dataModel, SIGNAL(quickViewRequested()), this, SLOT(onPeakDetected()));

    _videoTimeoutTimer.setSingleShot(true);
    connect(&_videoTimeoutTimer, SIGNAL(timeout()), this, SLOT(videoFeedTimeout()));
    connect(&_videoTimeoutTimer, SIGNAL(timeout()), &_dataModel, SIGNAL(videoTimeoutRequested()));
    connect(this, SIGNAL(error(QString)), &_dataModel, SIGNAL(error(QString)));

    connect(&_dataModel, SIGNAL(startRequested()), this, SLOT(start()));
    connect(&_dataModel, SIGNAL(stopRequested()), this, SLOT(stop()));
}

CameraLogic::~CameraLogic()
{
    stop();
}

void CameraLogic::start()
{
    QUrl audioPath = QUrl::fromUserInput(_dataModel.audioUrl());
    QNetworkRequest audioNr(audioPath);

    emit error("");

    if (_dataModel.username().isEmpty() == false)
    {
        QByteArray authValue = "Basic " + QByteArray(QString("%1:%2").arg(_dataModel.username()).arg(_dataModel.password()).toAscii()).toBase64();
        audioNr.setRawHeader("Authorization", authValue);
    }

    _audioFeed = _nam.get(audioNr);

    _wavFile.setWaveDevice(_audioFeed);

    connect(&_wavFile, SIGNAL(peakDetected()), this, SLOT(onPeakDetected()));
}

void CameraLogic::stop()
{
    _videoTimeoutTimer.stop();

    if (_audioFeed != NULL)
    {
        _wavFile.setWaveDevice(NULL);
        _audioFeed->deleteLater();
    }

    videoFeedTimeout();
}

void CameraLogic::onPeakDetected()
{
    QUrl videoPath = QUrl::fromUserInput(_dataModel.videoUrl());
    QNetworkRequest videoNr(videoPath);

    if (_dataModel.username().isEmpty() == false)
    {
        QByteArray authValue = "Basic " + QByteArray(QString("%1:%2").arg(_dataModel.username()).arg(_dataModel.password()).toAscii()).toBase64();
        videoNr.setRawHeader("Authorization", authValue);
    }

    _videoFeed = _nam.get(videoNr);

    if (_videoFeed->isRunning())
    {
        disconnect(&_wavFile, SIGNAL(peakDetected()), this, SLOT(onPeakDetected()));
        _mjpegFile.setVideoDevice(_videoFeed);
        _wavFile.play();
        _videoTimeoutTimer.setInterval(_dataModel.videoTimeout() * 1000);
        _videoTimeoutTimer.start();
    }
}

void CameraLogic::streamEnded(QNetworkReply *reply)
{
    switch (reply->error())
    {
    case QNetworkReply::OperationCanceledError:
        return;
    case QNetworkReply::NoError:
        start();
    default:
        emit error(reply->errorString());
    }
}

void CameraLogic::videoFeedTimeout()
{
    _wavFile.stop();
    connect(&_wavFile, SIGNAL(peakDetected()), this, SLOT(onPeakDetected()));

    if (_videoFeed != NULL)
    {
        qDebug("Video timeout or stop");

        _mjpegFile.setVideoDevice(NULL);
        _videoFeed->abort();
        _videoFeed->deleteLater();
        _videoFeed = NULL;
    }
}

